home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / raw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-10  |  15.5 KB  |  573 lines

  1. /* 
  2.  * raw.c --
  3.  *
  4.  *    Protocol-dependent routines to implement the semantics of
  5.  *    the socket operations defined in inetSocket.c. The routines in
  6.  *    this file handle low-level IP-based protocols for "raw" sockets.
  7.  *    A raw socket is used to send and receive non-UDP and non-TCP packets.
  8.  *    For example, it can be used to send ICMP echo packets.
  9.  *
  10.  * Copyright 1987 Regents of the University of California
  11.  * All rights reserved.
  12.  * Permission to use, copy, modify, and distribute this
  13.  * software and its documentation for any purpose and without
  14.  * fee is hereby granted, provided that the above copyright
  15.  * notice appear in all copies.  The University of California
  16.  * makes no representations about the suitability of this
  17.  * software for any purpose.  It is provided "as is" without
  18.  * express or implied warranty.
  19.  */
  20.  
  21. #ifndef lint
  22. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/raw.c,v 1.5 90/07/09 11:03:56 tve Exp $ SPRITE (Berkeley)";
  23. #endif not lint
  24.  
  25.  
  26. #include "sprite.h"
  27. #include "inet.h"
  28. #include "ipServer.h"
  29. #include "stat.h"
  30. #include "raw.h"
  31. #include "socket.h"
  32. #include "sockInt.h"
  33. #include "ip.h"
  34. #include "route.h"
  35.  
  36. /*
  37.  * Maximum amount of data that can be stored in a raw socket's send
  38.  * and receive buffers. 
  39.  */
  40.  
  41. #define RECV_BUF_SIZE    2048
  42. #define SEND_BUF_SIZE    2048
  43.  
  44. static void Output();
  45.  
  46.  
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * Raw_SocketOpen --
  52.  *
  53.  *    Does IP-specific actions for opening a new socket. The client
  54.  *    must have the super-user's user ID to open the socket.
  55.  *
  56.  * Results:
  57.  *    SUCCESS            - the socket was initialized.
  58.  *    GEN_NO_PERMISSION    - the client did not have the proper user ID.
  59.  *
  60.  * Side effects:
  61.  *    The max sizes for the send and receive buffers are set.
  62.  *
  63.  *----------------------------------------------------------------------
  64.  */
  65.  
  66. Raw_SocketOpen(sockPtr, userID)
  67.     Sock_SharedInfo    *sockPtr;    /* Socket to be opened. */
  68.     int            userID;        /* Client's user ID. */
  69. {
  70.     if (userID != PROC_SUPER_USER_ID) {
  71.     return(GEN_NO_PERMISSION);
  72.     }
  73.  
  74.     sockPtr->state = READY;
  75.     sockPtr->protocol = NET_IP_PROTOCOL_IP;
  76.     Sock_BufAlloc(sockPtr, SOCK_RECV_BUF, RECV_BUF_SIZE);
  77.     Sock_BufAlloc(sockPtr, SOCK_SEND_BUF, SEND_BUF_SIZE);
  78.     return(SUCCESS);
  79. }
  80.  
  81.  
  82. /*
  83.  *----------------------------------------------------------------------
  84.  *
  85.  * Raw_SocketClose --
  86.  *
  87.  *    Removes data from the socket's read and write queues.
  88.  *
  89.  * Results:
  90.  *    SUCCESS        - always returned.
  91.  *
  92.  * Side effects:
  93.  *    Deallocates buffers in the read and write queues.
  94.  *
  95.  *----------------------------------------------------------------------
  96.  */
  97.  
  98. ReturnStatus
  99. Raw_SocketClose(sockPtr)
  100.     Sock_SharedInfo    *sockPtr;    /* Socket to be closed. */
  101. {
  102.     Sock_BufRemove(sockPtr, SOCK_RECV_BUF, -1);
  103.     Sock_BufRemove(sockPtr, SOCK_SEND_BUF, -1);
  104.     return(SUCCESS);
  105. }
  106.  
  107.  
  108. /*
  109.  *----------------------------------------------------------------------
  110.  *
  111.  * Raw_SocketRead --
  112.  *
  113.  *    Supplies data to a client doing a read on a raw socket.
  114.  *    Normally the packet data is copied to the buffer. If the
  115.  *    packet is smaller than the buffer, no additional packets 
  116.  *    are read so the client will get a short read. If the buffer
  117.  *    is too small, the remaining data in the packet is not saved 
  118.  *    for the next read. Normally, the packet is removed from the
  119.  *    queue and the memory is deallocated once it is read. This
  120.  *    is not the case when the flag NET_PEEK is given.
  121.  *
  122.  * Results:
  123.  *    SUCCESS            - the data were copied to the buffer.
  124.  *    FS_WOULD_BLOCK        - nothing to read.
  125.  *    NET_BAD_OPERATION    - tried to read out-of-band data (not
  126.  *                  defined for this socket type).
  127.  *              
  128.  * Side effects:
  129.  *    The read queue is shortened.
  130.  *
  131.  *----------------------------------------------------------------------
  132.  */
  133.  
  134. ReturnStatus
  135. Raw_SocketRead(privPtr, bufSize, buffer, amountReadPtr)
  136.     Sock_PrivInfo    *privPtr;    /* Ptr to socket's per-process info. */
  137.     int        bufSize;        /* # of bytes in buffer. */
  138.     Address    buffer;            /* Place to put the data. */
  139.     int        *amountReadPtr;        /* # of bytes actually put in buffer. */
  140. {
  141.     ReturnStatus status;
  142.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  143.  
  144.     if ((sharePtr->state != READY) && (sharePtr->state != CONNECTED)) {
  145.     return(NET_BAD_OPERATION);
  146.     }
  147.  
  148.     if (privPtr->recvFlags & NET_OUT_OF_BAND) {
  149.     return(NET_BAD_OPERATION);
  150.     }
  151.  
  152.     status = Sock_BufFetch(sharePtr, privPtr->recvFlags, bufSize, buffer, 
  153.             amountReadPtr, &privPtr->recvFrom);
  154.  
  155.     /*
  156.      * Clear the recvFlags because they are only good for 1 read operation.
  157.      */
  158.     if (status == SUCCESS) {
  159.     privPtr->recvFlags = 0;
  160.     }
  161.  
  162.     return(status);
  163. }
  164.  
  165.  
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * Raw_SocketWrite --
  170.  *
  171.  *    Takes data from a write call by a client and causes the data
  172.  *    to be sent out on the network.
  173.  *
  174.  * Results:
  175.  *    SUCCESS            - the data were sent.
  176.  *    NET_BAD_OPERATION    - the send flags were not 0 (the flag
  177.  *                  values aren't valid for this operation).
  178.  *    FS_BUFFER_TOO_BIG    - the amount of data to send was larger than 
  179.  *                  the amount allowed.
  180.  *
  181.  * Side effects:
  182.  *    The data will be sent in a packet.
  183.  *
  184.  *----------------------------------------------------------------------
  185.  */
  186.  
  187. ReturnStatus
  188. Raw_SocketWrite(privPtr, packetPtr, amtWrittenPtr)
  189.     Sock_PrivInfo    *privPtr;
  190.     IPS_Packet    *packetPtr;        /* Packet containing data to be
  191.                      * sent on the network. */
  192.     int        *amtWrittenPtr;        /* # of bytes sent to the remote host.*/
  193. {
  194.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  195.  
  196.     *amtWrittenPtr = 0;
  197.  
  198.     if (packetPtr->dataLen > 
  199.          Sock_BufSize(sharePtr, SOCK_SEND_BUF, SOCK_BUF_MAX_SIZE)) {
  200.     return(FS_BUFFER_TOO_BIG);
  201.     }
  202.  
  203.     if ((sharePtr->state != READY) && (sharePtr->state != CONNECTED)) {
  204.     return(NET_BAD_OPERATION);
  205.     }
  206.  
  207.  
  208.     if (privPtr->sendInfoValid) {
  209.     /*
  210.      * The send info flags are not valid for raw sockets.
  211.      */
  212.     if (privPtr->sendInfo.flags != 0) {
  213.         return(NET_BAD_OPERATION);
  214.     }
  215.  
  216.     /*
  217.      * See if the client has given us an explicit address about
  218.      * where to send the packet. 
  219.      */
  220.  
  221.     privPtr->sendInfoValid = FALSE;
  222.     if (privPtr->sendInfo.addressValid) {
  223.         /*
  224.          * If the socket's connected, the user can't specify a different
  225.          * destination.
  226.          */
  227.         if (sharePtr->state == CONNECTED) {
  228.         return(NET_ALREADY_CONNECTED);
  229.         }
  230.         sharePtr->sentTo = privPtr->sendInfo.address.inet;
  231.  
  232.     } else {
  233.         /*
  234.          * If the socket's not connected, we don't have a valid 
  235.          * destination address.
  236.          */
  237.         if (sharePtr->state != CONNECTED) {
  238.         return(NET_NOT_CONNECTED);
  239.         }
  240.         sharePtr->sentTo = sharePtr->remote;
  241.     }
  242.  
  243.     } else {
  244.     if (sharePtr->state != CONNECTED) {
  245.         return(NET_NOT_CONNECTED);
  246.     }
  247.     sharePtr->sentTo = sharePtr->remote;
  248.     }
  249.  
  250.     *amtWrittenPtr = packetPtr->dataLen;
  251.  
  252.     Output(sharePtr, sharePtr->local.address, sharePtr->sentTo.address, 
  253.         packetPtr);
  254.  
  255.     return(SUCCESS);
  256. }
  257.  
  258.  
  259. /*
  260.  *----------------------------------------------------------------------
  261.  *
  262.  * Raw_SocketSelect --
  263.  *
  264.  *    Handles raw socket-specific checks to see if a socket is ready for
  265.  *    reading.  The socket is always writable because buffering is not done.
  266.  *
  267.  * Results:
  268.  *    An or'd combination of FS_READBLE and FS_WRITABLE.
  269.  *
  270.  * Side effects:
  271.  *    None.
  272.  *
  273.  *----------------------------------------------------------------------
  274.  */
  275.  
  276. int
  277. Raw_SocketSelect(sockPtr)
  278.     Sock_SharedInfo *sockPtr;    /* Socket to check the readiness of. */
  279. {
  280.     int flags = FS_WRITABLE;
  281.  
  282.     /*
  283.      * The socket is readble only if there's data in the read queue.
  284.      */
  285.     if (Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_USED) > 0) {
  286.     flags |= FS_READABLE;
  287.     }
  288.     return(flags);
  289. }
  290.  
  291.  
  292. /*
  293.  *----------------------------------------------------------------------
  294.  *
  295.  * Raw_SocketBind --
  296.  *
  297.  *    Assigns the local IP address for the socket. This address is used
  298.  *    to reject incoming packets with an unwanted destination address.
  299.  *
  300.  * Results:
  301.  *    SUCCESS            - the operation was successful.
  302.  *    NET_ADDRESS_NOT_AVAIL    - the caller gave an address that doesn't
  303.  *                  correspond to this host.
  304.  * Side effects:
  305.  *    The local IP address for a socket is assigned.
  306.  *
  307.  *----------------------------------------------------------------------
  308.  */
  309.  
  310. /*ARGSUSED*/
  311. ReturnStatus
  312. Raw_SocketBind(sockPtr, addrPtr, userID)
  313.     register Sock_SharedInfo *sockPtr;    /* Socket to be bound. */
  314.     Net_InetSocketAddr    *addrPtr;    /* Local address to assign to the 
  315.                      * socket. */
  316.     int        userID;            /* User ID of the client. Ignored. */
  317. {
  318.     /*
  319.      * If a specific IP address is given, make sure it is valid for
  320.      * this host (i.e., it is one of the addresses assigned to the host).
  321.      *
  322.      * Only set the SOCK_RAW_HAVE_LOCAL_ADDR flag if a non-wildcard address
  323.      * is given. The port value in addrPtr is ignored.
  324.      */
  325.     if (addrPtr->address != Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  326.     if (!Rte_ValidateAddress(addrPtr->address)) {
  327.         return(NET_ADDRESS_NOT_AVAIL);
  328.     }
  329.     sockPtr->flags |= SOCK_RAW_HAVE_LOCAL_ADDR;
  330.     }
  331.     sockPtr->local = *addrPtr;
  332.     return(SUCCESS);
  333. }
  334.  
  335.  
  336. /*
  337.  *----------------------------------------------------------------------
  338.  *
  339.  * Raw_SocketConnect --
  340.  *
  341.  *    Assigns a remote host address to a socket. From now on, only 
  342.  *    packets from this remote host will be accepted for this socket.
  343.  *
  344.  * Results:
  345.  *    SUCCESS        - always returned.
  346.  *
  347.  * Side effects:
  348.  *    The remote IP address for a socket is assigned.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352.  
  353. /*ARGSUSED*/
  354. ReturnStatus
  355. Raw_SocketConnect(sockPtr, remoteAddrPtr, initialize)
  356.     register Sock_SharedInfo    *sockPtr;    /* Socket to be connected. */
  357.     Net_InetSocketAddr    *remoteAddrPtr;    /* Remote address to send and receive
  358.                      * datagrams from. */
  359.     Boolean        initialize;    /* Ignored. */
  360. {
  361.     /*
  362.      * If the socket's already connected, disconnect it by zeroing 
  363.      * the remote <address,port> and removing all data in the recv queue.
  364.      */
  365.  
  366.     if (sockPtr->state == CONNECTED) {
  367.     sockPtr->remote.address    = Net_HostToNetInt(NET_INET_ANY_ADDR);
  368.     sockPtr->remote.port    = 0;
  369.     sockPtr->state        = READY;
  370.     Sock_BufRemove(sockPtr, SOCK_RECV_BUF, -1);
  371.     }
  372.  
  373.     sockPtr->remote = *remoteAddrPtr;
  374.     sockPtr->state  = CONNECTED;
  375.  
  376.     return(SUCCESS);
  377. }
  378.  
  379.  
  380. /*
  381.  *----------------------------------------------------------------------
  382.  *
  383.  * Raw_SocketShutdown --
  384.  *
  385.  *    Called by the client when it will not write any more data to 
  386.  *    the socket. Attempts to write data to the socket will fail.
  387.  *
  388.  * Results:
  389.  *    SUCCESS        - always returned.
  390.  *
  391.  * Side effects:
  392.  *    The socket is prevented from sending data.
  393.  *
  394.  *----------------------------------------------------------------------
  395.  */
  396.  
  397. /*ARGSUSED*/
  398. ReturnStatus
  399. Raw_SocketShutdown(sockPtr, how)
  400.     Sock_SharedInfo     *sockPtr;    /* Socket to be shutdown. */
  401.     int            how;        /* Type of shutdown wanted. */
  402. {
  403.     Sock_StopSending(sockPtr);
  404.     return(SUCCESS);
  405. }
  406.  
  407.  
  408. /*
  409.  *----------------------------------------------------------------------
  410.  *
  411.  * Raw_Input --
  412.  *
  413.  *    This routine is called when an IP packet arrives from the network
  414.  *    with a protocol that does not have a handler. The list of open
  415.  *    raw sockets is examined to see if any client wants the packet.
  416.  *    If the client wants the packet, a copy is made and appended to the 
  417.  *    socket's read queue and the client is notified that there's data 
  418.  *    to be read.
  419.  *
  420.  *    The caller of this routine must free the packet.
  421.  *
  422.  * Results:
  423.  *    None.
  424.  *
  425.  * Side effects:
  426.  *    New data is added to the read queue. The waiting client is
  427.  *    woken up.
  428.  *
  429.  *----------------------------------------------------------------------
  430.  */
  431.  
  432. void
  433. Raw_Input(protocol, srcAddr, destAddr, packetPtr)
  434.     int         protocol;    /* Protocol # in IP header. */
  435.     Net_InetAddress    srcAddr;    /* IP address of sender. */
  436.     Net_InetAddress    destAddr;    /* IP address of destination. */
  437.     IPS_Packet        *packetPtr;    /* Packet descriptor. */
  438. {
  439.     register Sock_SharedInfo    *sockPtr;
  440.     Net_InetSocketAddr        sockAddr;
  441.     Address            data;
  442.  
  443.     sockAddr.address = srcAddr;
  444.     sockAddr.port = 0;
  445.  
  446.     /*
  447.      * Go through all open raw sockets and see if anyone wants the packet.
  448.      */
  449.     sockPtr = (Sock_SharedInfo *) NULL;
  450.     while (TRUE) {
  451.     sockPtr = Sock_ScanList(RAW_PROTO_INDEX, sockPtr);
  452.     if (sockPtr == (Sock_SharedInfo *) NULL) {
  453.         break;
  454.     }
  455.  
  456.     /*
  457.      * If the socket wants a specific protocol, make sure the packet's
  458.      * protocol # matches. If the socket's protocol is NET_IP_PROTOCOL_IP,
  459.      * then it will get packets with NET_IP_PROTOCOL_IP and any other
  460.      * protocol.
  461.      */
  462.  
  463.     if ((sockPtr->protocol != NET_IP_PROTOCOL_IP) && 
  464.         (sockPtr->protocol != protocol)) {
  465.         continue;
  466.     }
  467.  
  468.     if ((sockPtr->flags & SOCK_RAW_HAVE_LOCAL_ADDR) &&
  469.         (destAddr != sockPtr->local.address)) {
  470.         continue;
  471.     }
  472.     if ((sockPtr->state == CONNECTED) &&
  473.         (srcAddr != sockPtr->remote.address)) {
  474.         continue;
  475.     }
  476.  
  477.     /*
  478.      * Make sure there's enough room in the buffer before we
  479.      * make a copy of the packet. It's a hack but saves a copy
  480.      * if the buffer can't take the packet.
  481.      */
  482. #ifndef    REAL_RAW
  483.     if (packetPtr->dataLen > Sock_BufSize(sockPtr, SOCK_RECV_BUF, 
  484.             SOCK_BUF_FREE)) {
  485.  
  486.         stats.sock.buffer.append++;
  487.         stats.sock.buffer.appendFail++;
  488.         continue;
  489.     }
  490.     data = malloc((unsigned int) packetPtr->dataLen);
  491.     bcopy(packetPtr->data, data, packetPtr->dataLen);
  492.  
  493.     (void) Sock_BufAppend(sockPtr, SOCK_RECV_BUF, TRUE, packetPtr->dataLen, 
  494.             data, data, &sockAddr, (int *)NULL);
  495. #else    REAL_RAW
  496.     if (packetPtr->dataLen+sizeof(Net_IPHeader) > Sock_BufSize(sockPtr,
  497.         SOCK_RECV_BUF, SOCK_BUF_FREE)) {
  498.  
  499.         stats.sock.buffer.append++;
  500.         stats.sock.buffer.appendFail++;
  501.         continue;
  502.     }
  503.     data = malloc((unsigned int) packetPtr->dataLen+sizeof(Net_IPHeader));
  504.     bcopy(packetPtr->ipPtr, data, sizeof(Net_IPHeader));
  505.     bcopy(packetPtr->data, data+sizeof(Net_IPHeader), packetPtr->dataLen);
  506.  
  507.     (void) Sock_BufAppend(sockPtr, SOCK_RECV_BUF, TRUE,
  508.             packetPtr->dataLen+sizeof(Net_IPHeader),
  509.             data, data, &sockAddr, (int *)NULL);
  510. #endif    REAL_RAW
  511.     Sock_NotifyWaiter(sockPtr, FS_READABLE);
  512.     }
  513. }
  514.  
  515.  
  516. /*
  517.  *----------------------------------------------------------------------
  518.  *
  519.  * Output --
  520.  *
  521.  *    This routine formats an IP packet and causes it to be queued for
  522.  *    output.
  523.  *
  524.  * Results:
  525.  *    None.
  526.  *
  527.  * Side effects:
  528.  *    An IP packet is queued for output.
  529.  *
  530.  *----------------------------------------------------------------------
  531.  */
  532.  
  533. static void
  534. Output(sockPtr, local, remote, packetPtr)
  535.     register Sock_SharedInfo *sockPtr;    /* Socket info for the sender. */
  536.     Net_InetAddress    local;        /* Source address for the packet. */
  537.     Net_InetAddress    remote;        /* Destination of the packet. */
  538.     register IPS_Packet *packetPtr;    /* Packet descriptor. */
  539. {
  540.     int    timeToLive = NET_IP_MAX_TTL;
  541.     int protocol = sockPtr->protocol;
  542.  
  543.     if (!(sockPtr->flags & SOCK_RAW_HAVE_LOCAL_ADDR) ||
  544.     (local == Net_HostToNetInt(NET_INET_ANY_ADDR))) {
  545.     local = Rte_GetOfficialAddr(FALSE);
  546.     }
  547.  
  548. #ifdef    REAL_RAW
  549.     /* If REAL_RAW is defined, we expect the user to give us a complete
  550.      * packet, INCLUDING the (partially filled-in) ip header. For the moment,
  551.      * all we care about in the ip header is the time-to-live and protocol
  552.      * fields. This hack is to support the traceroute program.
  553.      */
  554.     timeToLive = ((Net_IPHeader *)packetPtr->data)->timeToLive;
  555.     protocol = ((Net_IPHeader *)packetPtr->data)->protocol;
  556.     (Address)packetPtr->data += sizeof(Net_IPHeader);
  557.     packetPtr->dataLen -= sizeof(Net_IPHeader);
  558. #endif    REAL_RAW
  559.  
  560.     packetPtr->hdrLen = 0;
  561.     IP_FormatPacket(protocol, timeToLive, local, remote,
  562.             packetPtr);
  563.  
  564.     if (ips_Debug) {
  565.     (void) fprintf(stderr, "(Raw)Output: %d bytes, <%x> --> <%x>\n",
  566.         packetPtr->dataLen, local, remote);
  567.     }
  568.     stats.raw.send.total++;
  569.     stats.raw.send.dataLen += packetPtr->dataLen;
  570.  
  571.     IP_QueueOutput(packetPtr);
  572. }
  573.